package com.guyu.plugin.satoken.utils;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaTokenConsts;
import com.alibaba.fastjson2.JSON;
import com.guyu.plugin.satoken.context.LoginUser;
import jakarta.servlet.http.HttpServletRequest;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

import java.util.Objects;


@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class LoginHelper {

    public static final String USER_INFO_KEY = "userinfo";


    /**
     * 登录系统 基于 设备类型
     * 针对相同用户体系不同设备
     *
     * @param loginUser 登录用户信息
     * @param stpLogic  逻辑实现类
     */
    public static void login(LoginUser loginUser, StpLogic stpLogic) {
        stpLogic.login(loginUser.getLoginId());
        stpLogic.getSession().set(USER_INFO_KEY, JSON.toJSONString(loginUser));
    }

    /**
     * 获取用户
     */
    public static <T> T getLoginUser(SaSession saSession, Class<T> clazz) {
        if (Objects.isNull(saSession)) {
            return null;
        }
        Object userInfo = saSession.get(USER_INFO_KEY);
        if (Objects.isNull(userInfo)) {
            return null;
        }
        return JSON.parseObject(userInfo.toString(), clazz);
    }

    /**
     * 获取当前请求的用户
     */
    public static <T> T getLoginUser(StpLogic stpLogic, Class<T> clazz) {
        SaSession session = stpLogic.getSession();
        return getLoginUser(session, clazz);
    }

    /**
     * 获取用户基于token
     */
    public static <T> T getLoginUser(String token, StpLogic stpLogic, Class<T> clazz) {
        SaSession session = stpLogic.getTokenSessionByToken(token);
        return getLoginUser(session, clazz);
    }

    /**
     * 获取用户基于token
     */
    public static <T> T getLoginUser(Object loginId, StpLogic stpLogic, Class<T> clazz) {
        SaSession saSession = stpLogic.getSessionByLoginId(loginId);
        return LoginHelper.getLoginUser(saSession, clazz);
    }


    /**
     * 获取用户(多级缓存)
     */
    public static <T> T getLoginUser(HttpServletRequest request, StpLogic stpLogic, Class<T> clazz) {
        String tokenValue = getTokenValue(request, stpLogic);
        return getLoginUser(tokenValue, stpLogic, clazz);
    }

    /**
     * 获取请求token
     */
    public static String getTokenValue(HttpServletRequest request, StpLogic stpLogic) {
        // 1、获取token名称
        String tokenName = stpLogic.getTokenName();
        // 2、根据token名称获取token值
        String tokenValue = request.getHeader(tokenName);
        // 3、如果配置打开了前缀模式，则二次处理一下
        String tokenPrefix = stpLogic.getConfigOrGlobal().getTokenPrefix();
        if (SaFoxUtil.isNotEmpty(tokenPrefix)) {
            // 情况3.1：如果提交的 token 为空，则转为 null
            if (SaFoxUtil.isEmpty(tokenValue)) {
                tokenValue = null;
            }

            // 情况3.2：如果 token 有值，但是并不是以指定的前缀开头
            else if (!tokenValue.startsWith(tokenPrefix + SaTokenConsts.TOKEN_CONNECTOR_CHAT)) {
                tokenValue = null;
            } else {
                // 情况3.3：代码至此，说明 token 有值，且是以指定的前缀开头的，现在裁剪掉前缀
                tokenValue = tokenValue.substring(tokenPrefix.length() + SaTokenConsts.TOKEN_CONNECTOR_CHAT.length());
            }
        }
        // 4、返回
        return tokenValue;
    }

    public static long paresLoginIdAsLong(Object loginId) {
        if (loginId instanceof Long) {
            return (Long) loginId;
        }
        return Long.parseLong(String.valueOf(loginId));
    }


    /**
     * 获取当前请求的用户ID
     */
    public static Long getLoginIdAsLong(StpLogic stpLogic) {
        return stpLogic.getLoginIdAsLong();
    }
}
